#include "fig_life_obj.h"
#include "fighter.h"
#include "fig_bullet.h"
#include "fig_sfx_manager.h"
#include "fig_sfx.h"
#include "fig_sounds.h"
#include "fig_award_tracker.h"
#include "fig_functions.h"
#include "fig_vars.h"
#include "fig_exploding_manager.h"

#include "input/moga.h"
#include "dd/dd_man.h"
#include "math/intersection.h"
#include "num/rand.h"


FIGLifeObj::FIGLifeObj() :  
						m_ToDie(false),
						m_GetHitCounter(0.0f),
						m_IsReadyToFire(false),
						m_IsHitTestCircle(false),
						m_ExplodeSize(1.0f),
						m_DelayDie(0.0f),
						m_ExplodSfx(FIGSfx::EXPLODING_TYPE_NORMAL),
						m_IsHitAble(true),
						m_DamageForColliding(0),
						m_ExplodSoundSfx(FIGSounds::EXPLOSION_SMALL_1),
						m_IsAlive(false),
						m_Life(0),
						m_MaxLife(0),
						m_ExtraLife(0),
						m_OffsetScale(1.0f),
						m_SkipExplodeSingle(false)
					
{
	m_MaxLife = m_Life = 2;
	m_ShootCounter.SetLimit(1.0f);
}



 
void	FIGLifeObj::Tick(float dt)
{
	if(m_ToDie)
	{
		if(m_DelayDie > 0)
		{
			m_DelayDie -= dt;
			return;
		}
		
       OnDie();
	}

	if(!m_IsAlive)
		return;

	if(m_GetHitCounter > 0)
 		m_GetHitCounter -= dt;

	if(m_IsReadyToFire)
	{
		m_ShootCounter.Tick(dt);
		if(m_ShootCounter.IsReady())
		{
			m_ShootCounter.Reset();
			OnShoot();
		}
	}
	
	
	
}

 
  
bool	FIGLifeObj::HitTest(FIGBullet* pBullet)
{
	if(!m_IsHitAble)
		return false;

	if(!m_IsAlive)
		return false;

	if(m_Life <= 0)
		return false;
	
	if(pBullet->IsOwnHitTest())
		return pBullet->OwnHitTest(this);
	
 	if(HitTest(pBullet->GetPos()))
	{
		GotDamage(pBullet->GetDamagePower(),pBullet,false);
		pBullet->Kill();

		return true;
	}

	math::Vec2 Dir = pBullet->GetDirection();	
	Dir.Rotate(180.0f);
	Dir *= pBullet->GetRadius();

	for(int i = 0; i < (int)(pBullet->GetHowlong()/0.025f); i++)
	{
        if(HitTest(pBullet->GetPos() + ( Dir * (float)i)))
		{
       		GotDamage(pBullet->GetDamagePower(),pBullet,false);
			pBullet->Kill();

			return true;
		}
	}
	

	return false;
}


bool	FIGLifeObj::HitTest(const math::Vec2& Point)
{
	if(!m_IsHitAble)
		return false;

	if(m_IsHitTestCircle)
		return HitTestCircle(Point);

	return HitTest(GetSprite(),Point,GetPos());
	return false;

}

bool	FIGLifeObj::HitTest(ui::UISprite* pSprite, 
						  const math::Vec2& Point , 
						  const math::Vec2& SpritePos
						  )
{
	return FigFunctions::HitTest(pSprite,Point,SpritePos);

	return false;
}


bool	FIGLifeObj::HitTest(FIGLifeObj* pObj)
{
	//return false;

	if(!m_IsHitAble)
		return false;

	if(!m_IsAlive)
		return false;

	if(m_Life <= 0)
		return false;

	const float Radius = GetRadius() * Fighter::Instance().GetScale();
	
	if(pObj->HitTest( GetPos() - math::Vec2(0,-Radius)))
		return true;

	if(pObj->HitTest( GetPos() - math::Vec2(0, Radius)))
		return true;

	if(pObj->HitTest( GetPos() - math::Vec2( -Radius,0)))
		return true;

	if(pObj->HitTest( GetPos() - math::Vec2(Radius,0)))
		return true;

	if(pObj->HitTest( GetPos()))
		return true;
	 
	
	return false;
}

bool	FIGLifeObj::HitTest(const math::Vec2& MinA, const math::Vec2& MaxA, float DamageAmount)
{

	math::Vec2 MinB =   GetPos() - math::Vec2(GetRadius(),GetRadius());
	math::Vec2 MaxB =   GetPos() + math::Vec2(GetRadius(),GetRadius());

	
	//dd::Manager&	DD = dd::Manager::Instance();
	//const math::Vec2 Offset = Fighter::Instance().GetOffset();
	//DD.AddBox2D( MinB + Offset  , MaxB + Offset );

	bool IsHit = true;
	if( MinA.x > MaxB.x)
		IsHit = false;
	else if( MinA.y > MaxB.y)
		IsHit = false;
	else if( MaxA.x < MinB.x)
		IsHit = false;
	else if( MaxA.y < MinB.y)
		IsHit = false;      

	if(IsHit)
	{
		GotDamage(DamageAmount,NULL,false);
	}
	return IsHit;
	
	return false;
}

bool	FIGLifeObj::HitTestCircle(const math::Vec2& Point)
{
	if ( (GetPos() - Point).Magnitude() < GetRadius() * Fighter::Instance().GetScale() )
		return true;

	return false;
	
}

void	FIGLifeObj::GotDamage(float Amount,FIGBullet* pBullet, bool Force)
{
	
	if(m_Life < 0)
		return;

	m_Life -= Amount;

	math::Vec2 Pos;
	if(pBullet)
		Pos = pBullet->GetPos();
	else
		Pos = GetPos();

	FIGSfx* pSFX = NULL;

	if(pBullet)
	{
		if( pBullet->GetType() == FIGBullet::BULLET_TYPE_PLAYER_ROCKET ||
			pBullet->GetType() == FIGBullet::BULLET_TYPE_PLAYER_TOPIDO
			)
		{
			pSFX = FIGSFXManager::Instance().Spawn(FIGSfx::EXPLODING_TYPE_ROKETHIT,
											Pos ,
											1.0f,
											0,false,
											FIGSounds::ROCKET_IMPACT
											);
		}
		else
			pSFX = FIGSFXManager::Instance().Spawn(FIGSfx::EXPLODING_TYPE_SMALLHIT, Pos , 1.0f);

		if(pSFX)
		{
			AddSFX(pSFX);			
			pSFX->SetIsRenderByOwner(true);
		}
	}

	if(m_Life <= 0)
	{
		m_ToDie = true;		
		OnStartDying();
	}
	else
	{
		

		m_GetHitCounter = 0.1f;
	}
	
}

void	FIGLifeObj::ReSpawn()
{
	m_SFXs.resize(0);
	int Difficulty = FIGVars::Instance()->GetInt(FIGVars::VAR_NAMES_DIFFICULTY);

	if(input::MOGAJoystick::Instance().IsConnected())
	{
		// make it a little harder
		Difficulty = 2;		
	}

	m_ExtraLife =   m_MaxLife *  Difficulty * 0.35f;

	m_IsAlive = true;
	m_Life = m_MaxLife + m_ExtraLife;
	m_GetHitCounter = 0;
	m_IsReadyToFire = false;
	m_ShootCounter.Reset();

}




bool	FIGLifeObj::IsInSideScreen()
{
	
	if( GetPos().x + (GetSize().x*0.5f) < 0)
		return false;

	if(GetPos().x - (GetSize().x*0.5f) > 1)
		return false;

	if( GetPos().y + (GetSize().y*0.5f) < 0)
		return false;

	if(GetPos().y - (GetSize().y*0.5f) > 1)
		return false;

		
	return true;
}

void	FIGLifeObj::OnDie()
{
	
	FIGAwardTracker::Instance().EnemyKill((int)m_MaxLife);
	m_ToDie = false;
	m_IsAlive = false;	
	OnExplode();
	
		
}

void		FIGLifeObj::OnExplode()
{
		

	FIGSfx* pSFX = NULL;
	
	if(!m_SkipExplodeSingle)
	{
		//pSFX = FIGSFXManager::Instance().Spawn(	
		//											FIGSfx::EXPLODING_TYPE_EXPLODEBANG, 
		//											GetPos(),
		//											m_ExplodeSize,
		//											0,
		//											false,
		//											FIGSounds::SFX_NONE
		//											);
		if(pSFX)
		{
			pSFX->SetOffsetScale(m_OffsetScale);
			AddSFX(pSFX);			

			if(IsGroundObject())
				pSFX->SetIsRenderAtGround(true);
		}
	}

	//pSFX = FIGSFXManager::Instance().Spawn(	
	//											m_ExplodSfx, 
	//											GetPos(),
	//											m_ExplodeSize,
	//											0,
	//											false,
	//											m_ExplodSoundSfx
	//											);
	if(pSFX)
	{
		pSFX->SetOffsetScale(m_OffsetScale);
		AddSFX(pSFX);			

		if(IsGroundObject())
				pSFX->SetIsRenderAtGround(true);
	}

	FIGExplodingManager::Instance().Spawn(FIGExploding::EXPLODING_GEMINI, GetPos(), m_ExplodeSize);
	Fighter::Instance().ShakeScreen(m_ExplodeSize);
	
}

void		FIGLifeObj::RenderSFX(const math::Vec2& Offset, float Scale)
{
	for(int i = 0; i < (int)m_SFXs.size(); i++)
	{
		FIGSfx* pSFX = m_SFXs[i];
		if(pSFX && pSFX->GetIsRenderByOwner() && pSFX->IsOwner(this))
			pSFX->Render(Offset,Scale);
	}
}

void		FIGLifeObj::AddSFX(FIGSfx* pSFX)
{
	if(!pSFX)
		return;

	for(int i = 0; i < (int)m_SFXs.size(); i++)
	{
		if(pSFX == m_SFXs[i])
		{
			pSFX->SetOwner(this); // renew 
			return;		
		}
	}

	m_SFXs.push_back(pSFX);
	pSFX->SetOwner(this);
}
